package com.doublethread.easymart.config;

import com.alibaba.druid.pool.DruidDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.Connection;

/**
 * 自定义健康检查指示器
 */
@Slf4j
@Component("custom")
@Profile("!test")
public class CustomHealthIndicator implements HealthIndicator {

    @Autowired
    private DataSource dataSource;

    @Override
    public Health health() {
        try {
            Health.Builder builder = Health.up();

            checkDruidDataSource(builder);
            checkSystemMemory(builder);

            return builder.build();

        } catch (Exception e) {
            log.error("健康检查失败", e);
            return Health.down()
                    .withDetail("error", e.getMessage())
                    .build();
        }
    }

    /**
     * 检查数据源状态
     */
    private void checkDruidDataSource(Health.Builder builder) {
        try {
            if (dataSource instanceof DruidDataSource) {
                DruidDataSource druidDataSource = (DruidDataSource) dataSource;

                int activeCount = druidDataSource.getActiveCount();
                int maxActive = druidDataSource.getMaxActive();
                int poolingCount = druidDataSource.getPoolingCount();

                builder.withDetail("database", "UP")
                        .withDetail("druid.activeConnections", activeCount)
                        .withDetail("druid.maxConnections", maxActive)
                        .withDetail("druid.poolingConnections", poolingCount)
                        .withDetail("druid.connectionUsage", String.format("%.2f%%",
                                (double) activeCount / maxActive * 100));

                try (Connection connection = dataSource.getConnection()) {
                    boolean isValid = connection.isValid(3);
                    builder.withDetail("druid.connectionValid", isValid);
                }
            }
        } catch (Exception e) {
            log.error("数据库检查失败", e);
            builder.withDetail("database", "DOWN")
                    .withDetail("database.error", e.getMessage());
        }
    }


    /**
     * 检查系统内存使用情况
     */
    private void checkSystemMemory(Health.Builder builder) {
        try {
            Runtime runtime = Runtime.getRuntime();
            long totalMemory = runtime.totalMemory();
            long freeMemory = runtime.freeMemory();
            long usedMemory = totalMemory - freeMemory;
            long maxMemory = runtime.maxMemory();

            double memoryUsage = (double) usedMemory / maxMemory * 100;

            builder.withDetail("memory.total", formatBytes(totalMemory))
                    .withDetail("memory.used", formatBytes(usedMemory))
                    .withDetail("memory.free", formatBytes(freeMemory))
                    .withDetail("memory.max", formatBytes(maxMemory))
                    .withDetail("memory.usage", String.format("%.2f%%", memoryUsage));

            if (memoryUsage > 90) {
                builder.withDetail("memory.status", "WARNING");
                log.warn("内存使用率过高: {:.2f}%", memoryUsage);
            } else {
                builder.withDetail("memory.status", "OK");
            }
        } catch (Exception e) {
            log.error("内存检查失败", e);
            builder.withDetail("memory", "ERROR")
                    .withDetail("memory.error", e.getMessage());
        }
    }

    /**
     * 格式化字节数
     */
    private String formatBytes(long bytes) {
        if (bytes < 1024) return bytes + " B";
        if (bytes < 1024 * 1024) return String.format("%.2f KB", bytes / 1024.0);
        if (bytes < 1024 * 1024 * 1024) return String.format("%.2f MB", bytes / (1024.0 * 1024));
        return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024));
    }
}
